--------------------------------------------------------------
--															--
-- No Contest on Hit a.k.a. KL_YouShouldKillYourselfNow.pk3	--
--															--
-- Please read "read_nocontest.txt" for more info.			--
--															--
--------------------------------------------------------------

if (hmt_nocontestinit) then return end -- Do not run twice.

freeslot("sfx_hmexpl")
freeslot("sfx_hmtblo")
freeslot("sfx_hmtfrt")
freeslot("sfx_hmtchs")

local nocontest_cvtype = {Off = 0, Depends = 1, On = 2} -- generally

-- why isnt this a global by default???
local starttime = 6*TICRATE + (3*TICRATE/4)

local hmt_nocontest = CV_RegisterVar({
    "hmt_nocontest",
    "Depends",
    CV_NETVAR|CV_CALL|CV_NOINIT,
    nocontest_cvtype,
	func = function(var)
		if var.value == 2 then
			hmt_alertcons("No Contest on Hit is forced ".."\x85".."ENABLED!", true)
		elseif var.value == 0 then
			hmt_alertcons("No Contest on Hit is forced ".."\x85".."DISABLED!")
		end
	end
})

local hmt_nopitkill = CV_RegisterVar({
    "hmt_nopitkill",
    "Depends",
    CV_NETVAR,
    nocontest_cvtype
})

local hmt_nopowerkill = CV_RegisterVar({
    "hmt_nopowerkill",
    "Depends",
    CV_NETVAR,
    nocontest_cvtype
})

local hmt_noexitkill = CV_RegisterVar({
    "hmt_noexitkill",
    "Depends",
    CV_NETVAR,
    nocontest_cvtype
})

-- 4 isnt enough.
local hmt_randomkillsounds = {
	"sfx_hmtblo",
	"sfx_hmtfrt",
	"sfx_hmexpl",
	"sfx_hmtchs"
}

local function HMT_HandleNOCHitFeed(p, source)
	if (hitfeed) then
		local s = {{p.name, p.mo.hf_overridenamecolor or p.skincolor}, {skins[p.mo.skin].facemmap, p.skincolor}, p}
		if source.player then
			s = {{source.player.name, source.hf_overridenamecolor or source.player.skincolor}, {skins[source.skin].facemmap, source.player.skincolor}, source.player}
		end
		local v = {{p.name, p.mo.hf_overridenamecolor or p.skincolor}, {skins[p.mo.skin].facemmap, p.skincolor}, p}
		if (s[3] == v[3]) then s = nil end	-- source == victim, remove source
		
		-- need a better graphic for this
		HF_SendHitMessage(s, v, "K_HSNOC1")
	end
end

local function HMT_NoContestPlayer(player, source)
	-- Abort when hmt_noexitkill is enabled.
	if player.exiting and HMT_CheckVariable("hmt_noexitkill") then return end
	if player.pflags & PF_TIMEOVER then return end -- we're already timed out!
	-- no source? point to the player instead!
	if not source then source = player end
	
	HMT_HandleNOCHitFeed(player, source)
	
	player.exiting = 0
	player.lives = 0
	player.pflags = $|PF_TIMEOVER
	player.hmt_eliminated = 1
	-- hm...
	player.kartstuff[k_position] = HMT_GetNumPlayers2()
	player.kartstuff[k_growshrinktimer] = 0
	player.kartstuff[k_invincibilitytimer] = 0
	player.kartstuff[k_hyudorotimer] = 6*TICRATE
	if HugeQuest then
		player.huge = 0
		player.mo.sparkle = 0
	end
	P_DamageMobj(player.mo, nil, nil, 10000)
	local killsound = hmt_randomkillsounds[((leveltime + player.skincolor) % 4) + 1]
	S_StartSound(player.mo, _G[killsound])
	-- rub it in
	COM_BufInsertText(player, "tunes KRFAIL")
	
	-- spawn KABOOM because it doesnt spawn one
	local boom = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_FZEROBOOM)
	boom.scale = player.mo.scale
	boom.angle = player.mo.angle
end

local function HMT_HandleNormalDamage(player)
	if not HMT_CheckVariable("hmt_nocontest") then return end
	HMT_NoContestPlayer(player)
end

local function HMT_HandleDeathpit(player)
	if player.spectator then return end
	if leveltime < starttime then return end -- we dont want this to apply before we even start!!!!
	if not HMT_CheckVariable("hmt_nocontest") then return end
	if HMT_CheckVariable("hmt_nopitkill") then return end
	if player.playerstate == PST_DEAD and not (player.pflags & PF_TIMEOVER) then
		HMT_NoContestPlayer(player)
	end
end

local function HMT_HandlePlayerHUDCountdown(player)
	-- dont bother running
	if not HMT_CheckVariable("hmt_nocontest") then return end
	-- reset all values
	if leveltime < starttime then
		player.hmt_eliminated = 0
		player.deathcountdown = 0
		return
	end
	if (player.pflags & PF_TIMEOVER) and player.hmt_eliminated then
		player.deathcountdown = ($ or 0) + 1
	end
end

local function HMT_HandleGlobalHUDCountdown()
	-- dont bother running
	if not HMT_CheckVariable("hmt_nocontest") then return end
	-- unused?
end

local function HMT_HandleShouldSpin(p, inf, source)
	-- do regular behavior
	if not HMT_CheckVariable("hmt_nocontest") then return end
	
	-- reduce the amount of PlayerDamage hooks
	local no = (p.kartstuff[k_growshrinktimer] > 0 or p.kartstuff[k_invincibilitytimer])
	if HugeQuest then
		no = (p.kartstuff[k_growshrinktimer] > 0 or p.kartstuff[k_invincibilitytimer]) or (p.huge > 0 or p.mo.sparkle)
	end
	
	if inf and inf.valid and not no then
		HMT_NoContestPlayer(p, source)
	end
	
	-- powerkill stuff
	if HMT_CheckVariable("hmt_nopowerkill") then return end
	
	if HugeQuest then
		if (p.huge > 0 or p.mo.sparkle)
			if inf and inf.valid
				HMT_NoContestPlayer(p, source)
				return
			end
		end
	end
	
	if (p.kartstuff[k_growshrinktimer] > 0 or p.kartstuff[k_invincibilitytimer])
		if inf and inf.valid
			HMT_NoContestPlayer(p, source)
			return
		end
	end
	return
end

local function HMT_HandleShouldExplode(p, inf, source)
	if not HMT_CheckVariable("hmt_nocontest") then return end
	
	-- reduce the amount of PlayerDamage hooks
	local no = (p.kartstuff[k_growshrinktimer] > 0 or p.kartstuff[k_invincibilitytimer])
	if HugeQuest then
		no = (p.kartstuff[k_growshrinktimer] > 0 or p.kartstuff[k_invincibilitytimer]) or (p.huge > 0 or p.mo.sparkle)
	end
	
	if inf and inf.valid and not no then
		HMT_NoContestPlayer(p, source)
	end
	
	if not no then HMT_NoContestPlayer(p) end
	
	-- powerkill
	if HMT_CheckVariable("hmt_nopowerkill") then return end
	
	if HugeQuest then
		if p.huge > 0
		or p.mo.sparkle > 0
			if inf and inf.valid then
				HMT_NoContestPlayer(p, source)
				return
			end
			HMT_NoContestPlayer(p)
			return 
		end
	end
	if p.kartstuff[k_growshrinktimer] > 0
	or p.kartstuff[k_invincibilitytimer] > 0
		if inf and inf.valid then
			HMT_NoContestPlayer(p, source)
			return
		end
		HMT_NoContestPlayer(p)
		return 
	end
	return
end

local function HMT_HandleShouldDamage(mo, inf, source, damage)
    if not (mo and mo.valid and mo.player) then return end
	if not HMT_CheckVariable("hmt_nocontest") then return end
	
	local mop, mopks = mo.player, mo.player.kartstuff
	
	-- reduce the amount of PlayerDamage hooks
	local no = (mopks[k_growshrinktimer] > 0 or mopks[k_invincibilitytimer])
	if HugeQuest then
		no = (mopks[k_growshrinktimer] > 0 or mopks[k_invincibilitytimer]) or (mop.huge > 0 or mo.sparkle)
	end
	
	if damage >= 10000 then 
		if not (inflictor and inflictor.type == MT_SINK) then HMT_NoContestPlayer(mop) return end
	end -- for pits and respawns. we got that covered
	
	local source_f = nil
	if source.player then 
		source_f = source
	end
	if inflictor and inflictor.player then
		source_f = inflictor
	end
	
	if not no then HMT_NoContestPlayer(mop, source_f) end
	
	-- powerkill
	if HMT_CheckVariable("hmt_nopowerkill") then return end

	HMT_NoContestPlayer(mop, source_f)
	return
end

local countdown = 5*TICRATE
local countdown_2 = 0

addHook("NetVars", function(net)
	countdown = net(countdown)
	countdown_2 = net(countdown_2)
end)

hud.add(function(v, p, c)
	if not HMT_CheckVariable("hmt_nocontest") then return end -- dont run when off
	if (p and p.valid)
		if (p.deathcountdown and p.deathcountdown > (2*TICRATE)) and not countdown_2 then
			local maxfade = v.localTransFlag(v)>>V_ALPHASHIFT    -- value of V_HUDTRANS
			local fade = max(maxfade, (9 - ((p.deathcountdown - (2*TICRATE)))/4))
			
			if fade <= 9
				if (splitscreen)
					if (splitscreen) == 1 -- 2 players
						local hy = c.pnum == 2 and 176 or 76 -- starting pos for strings
						local flags = (c.pnum == 2 and V_SNAPTOBOTTOM or 0)|(fade<<V_ALPHASHIFT)
						
						v.drawString(160, hy, ("You have been eliminated."), flags, "center")
						v.drawString(160, hy+9, ("Wait until the next round."), flags, "center")
					else -- 3+ players
						local hx = (c.pnum == 2 or c.pnum == 4) and 240 or 80
						local hy = c.pnum > 2 and 176 or 76
						local flags = (c.pnum > 2 and V_SNAPTOBOTTOM or 0)|((c.pnum == 2 or c.pnum == 4) and V_SNAPTORIGHT or V_SNAPTOLEFT)|(fade<<V_ALPHASHIFT)
						
						v.drawString(hx-(v.stringWidth("You have been eliminated.", 0, "thin")/2), hy, "You have been eliminated.", flags, "thin")
						v.drawString(hx-(v.stringWidth("Wait until the next round.", 0, "thin")/2), hy+9, "Wait until the next round.", flags, "thin")
					end
				else
					v.drawString(160, 76, ("You have been eliminated."), V_SNAPTOBOTTOM|(fade<<V_ALPHASHIFT), "center")
					v.drawString(160, 85, ("Wait until the next round."), V_SNAPTOBOTTOM|(fade<<V_ALPHASHIFT), "center")
				end
			end
			return
		end
		if (countdown_2 and countdown_2 > (2*TICRATE))
			local maxfade = v.localTransFlag(v)>>V_ALPHASHIFT    -- value of V_HUDTRANS
			local fade = max(maxfade, (9 - ((countdown_2 - (2*TICRATE)))/4))
			
			if fade <= 9
				if (splitscreen)
					if (splitscreen) == 1 -- 2 players
						local hy = c.pnum == 2 and 176 or 76 -- starting pos for strings
						local flags = (c.pnum == 2 and V_SNAPTOBOTTOM or 0)|(fade<<V_ALPHASHIFT)
						
						v.drawString(160, hy, ("All players have been eliminated."), flags, "center")
						v.drawString(160, hy+9, ("The map will restart in a moment."), flags, "center")
					else -- 3+ players
						local hx = (c.pnum == 2 or c.pnum == 4) and 240 or 80
						local hy = c.pnum > 2 and 176 or 76
						local flags = (c.pnum > 2 and V_SNAPTOBOTTOM or 0)|((c.pnum == 2 or c.pnum == 4) and V_SNAPTORIGHT or V_SNAPTOLEFT)|(fade<<V_ALPHASHIFT)
						
						v.drawString(hx-(v.stringWidth("All players have been eliminated.", 0, "thin")/2), hy, "All players have been eliminated.", flags, "thin")
						v.drawString(hx-(v.stringWidth("The map will restart in a moment.", 0, "thin")/2), hy+9, "The map will restart in a moment.", flags, "thin")
					end
				else
					v.drawString(160, 76, ("All players have been eliminated."), V_SNAPTOBOTTOM|(fade<<V_ALPHASHIFT), "center")
					v.drawString(160, 85, ("The map will restart in a moment."), V_SNAPTOBOTTOM|(fade<<V_ALPHASHIFT), "center")
				end
			end
		end
	end
end)

-- what if theres no players left? dw mate i gotchu
local function HMT_HandleNoPlayersLeft()
	-- make sure it aint running spb attack
	if server.SPBArunning then return end -- dont handle this when spb attack is already running
	if not HMT_CheckVariable("hmt_nocontest") then return end
	if HMT_GetNumPlayers2() <= 0 then return end -- whats the point on running if there are actually no players
	if HMT_GetNumPlayers() <= 0 then -- IF we actually have no players left
		countdown = $ - 1
		countdown_2 = $ + 1
	end
	if countdown <= 0 then
		countdown = 5*TICRATE
		countdown_2 = 0
		COM_BufInsertText(server, "map "..G_BuildMapName(gamemap))
	end
end

addHook("MapChange", function()
	countdown = 5*TICRATE
	countdown_2 = 0
end)

local function HMT_HandleNOCChatMessage()
	if leveltime == 2*TICRATE then
		if HMT_CheckVariable("hmt_nocontest") then 
			hmt_alert("No Contest on Hit is ".."\x85".."ENABLED!", true)
		end
	end
end

addHook("PlayerThink", HMT_HandleDeathpit)
addHook("PlayerThink", HMT_HandlePlayerHUDCountdown)

addHook("ThinkFrame", HMT_HandleGlobalHUDCountdown)
addHook("ThinkFrame", HMT_HandleNoPlayersLeft)
addHook("ThinkFrame", HMT_HandleNOCChatMessage)

addHook("ShouldSpin", HMT_HandleShouldSpin)
addHook("ShouldExplode", HMT_HandleShouldExplode)
addHook("ShouldDamage", HMT_HandleShouldDamage)

rawset(_G, "hmt_nocontestinit", 1) -- We're done!